package cn.edu.sjtu.stap.cg.builder;

import java.util.*;

import org.aspectj.asm.*;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.*;

import cn.edu.sjtu.stap.cg.*;
import cn.edu.sjtu.stap.hg.*;

/**
 * Default CG builder.
 * 
 * @author William
 * 
 */
public class DefaultCgBuilder implements ICgBuilder {
    private PartialCgBuilder builder = new PartialCgBuilder();

    private AjCgBuilder ajBuilder = new AjCgBuilder();

    private Map<AbstractMethodDeclaration, CallGraph> cgs = null;

    private static DefaultCgBuilder instance = null;

    /**
     * Default Constructor.
     * 
     */
    public DefaultCgBuilder() {
        // Empty.
    }

    public static DefaultCgBuilder getInstance() {
        if (instance == null) {
            instance = new DefaultCgBuilder();
        }
        return instance;
    }

    public void initialize() {
        builder.initialize();
        ajBuilder.initialize();
    }

    public void buildCallGraph(HierarchyGraph hg, CompilationUnitDeclaration unit) {
        try {
            builder.setHierarchyGraph(hg);
            unit.traverse(builder, unit.scope);

            cgs = builder.getResult();
        } catch (Throwable e) {
            System.err.println("Error occurred in " + new String(unit.getFileName()));
            e.printStackTrace();
        }
    }

    public void buildCallGraph(AsmManager manager) {
        if (cgs == null) {
            throw new UnsupportedOperationException("Call graph should be built on AST first!");
        }

        // cgs will be updated according to the advice info.
        ajBuilder.buildAjCallGraph(manager, cgs);
    }

    public Map<AbstractMethodDeclaration, CallGraph> getResult() {
        return cgs;
    }

    public Set<AbstractMethodDeclaration> getProgramEntries() {
        return builder.getProgramEntries();
    }
}
